/******************************************************************************
 * FileName:    gwin_global_data.h
 * Desc:        全局变量
 *
 *
 * Author:      Lin
 * Notes:
 *
 ******************************************************************************/

#ifndef __GWIN_GLOBAL_DATA_H__
#define __GWIN_GLOBAL_DATA_H__


/*-------------------------- Includes ---------------------------------------*/
#include "gwin_board.h"
#include "gwin_misc_api.h"
#include "gwin_general_timer.h"
#include "gwin_general_clock.h"
#include "gwin_spec_nofity.h"

#include "miio_user_api.h"


/*-------------------------- Macro Definitions ------------------------------*/
#define PRODUCT_MARK_SIZE               ( 64 - 8 )  // 产品标识符 长度
#define PRODUCT_MARK_RESET              ( 1 )       // 产品标识符 重置参数（普通参数） 原因：解决产品已经烧录后，修改flash参数默认值。处理：每次重启后优先判断这个值，不相同则执行重置。操作：想要ota后需要重置，数值叠加1
#define PRODUCT_MARK_RESET_ALL_FORCE    ( 1 )       // 产品标识符 强制重置所有参数   原因：解决产品已经烧录后，修改flash分区大小。处理：每次重启后优先判断这个值，不相同则执行重置。操作：想要ota后需要重置，数值叠加1
#define PRODUCT_MARK_RESET_ALL_FORCE_FORCE  ( 1 )   // 产品标识符 强制重置所有参数（重置配网、重烧产品信息（慎重！！！））   原因：解决产品已经烧录后，修改flash分区大小。处理：每次重启后优先判断这个值，不相同则执行重置。操作：想要ota后需要重置，数值叠加1
#define SYS_UPLOAD_TIME                 ( 2 )       // 一段时间参数不变则上报 2秒
#define FORCE_UPLOAD_TIME_NETWORK       ( 1 )       // 一段时间参数后才上报数据 1秒 配网
#define FORCE_UPLOAD_TIME_GATT          ( 5 )       // 一段时间参数后才上报数据 5秒 蓝牙直连
#define MESH_REQUEST_INFO_TIME          ( 10 )      // mesh请求服务器信息 10秒
#define WAIT_UPLOAD_MIOT_RESEND_TIME    ( 12 )      // 补发 12秒 防止没有连接上网关就补发
#define CURTAIN_POSITION_MAX            ( 100 )     // 窗帘位置最大值
#define STROKE_MIN_MIN                  ( 0 )       // 行程最小值，单位：%，范围：0~50
#define STROKE_MIN_MAX                  ( 50 )      // 行程最小值，单位：%，范围：0~50
#define STROKE_MAX_MIN                  ( 51 )      // 行程最大值，单位：%，范围：51~100
#define STROKE_MAX_MAX                  ( 100 )     // 行程最大值，单位：%，范围：51~100


#if (GWIN_DEBUG_EN)
#define SYSTEM_DEBUG(...)               _GWIN_DEV_DEBUG(__VA_ARGS__)
#define USER_DEBUG(...)                 GWIN_DEV_DEBUG(__VA_ARGS__)
#define GWIN_OS_TIMER_ASSERT(timer)     if (NULL == (timer))                        \
                                        {                                           \
                                            GWIN_DEBUG("timer create NULL!!!");     \
                                            while(1);                               \
                                        }
#else
#define SYSTEM_DEBUG(...)
#define USER_DEBUG(...)
#define GWIN_OS_TIMER_ASSERT(timer)
#endif


/*-------------------------- Type Declarations ------------------------------*/
/**
 * @brief 用户存储区id
 */
typedef enum
{
    RECORD_ID_PRODUCT_MARK,
    RECORD_ID_PRODUCT_CFG,
    RECORD_ID_REBOOT_STATE,
    RECORD_ID_NETWORK,
    RECORD_ID_SYSTEM_UPLOAD,
    RECORD_ID_SETTING,
}record_id_t;
#define RECORD_ID_MIN                   RECORD_ID_PRODUCT_CFG

/**
 * @brief 系统参数表
 */
typedef struct
{
    uint16_t size;                      // 长度
    uint8_t *memory_addr;               // 内存地址
    uint8_t *defalut_addr;              // 默认地址
}system_param_default_t;

/**
 * @brief 产品标识符
 */
typedef struct
{
    uint8_t model_name[PRODUCT_MARK_SIZE];
    uint16_t reset_all;                 // 产品标识符 重置参数（普通参数）
    uint16_t reset_all_force;           // 产品标识符 强制重置所有参数
    uint16_t reset_all_force_force;     // 产品标识符 强制重置所有参数（带重置配网）
    uint16_t reserve;                   // 保留
}product_mark_t;

/**
 * @brief 网络
 */
typedef struct
{
    uint8_t provisioned         : 1;    // 配网状态
    uint8_t reserve1;                   // 保留
    uint16_t reserve2;                  // 保留
}network_t;

/**
 * @brief 重启原因
 */
typedef enum
{
    REBOOT_REASON_NONE,
    REBOOT_REASON_FACTORY_RESET,
    REBOOT_REASON_WDG,
    REBOOT_REASON_OTA,
    REBOOT_REASON_SW_REBOOT,
}reboot_reason_t;
#define REBOOT_REASON_RESTORE_STATE     REBOOT_REASON_FACTORY_RESET

/**
 * @brief 重启状态
 */
typedef struct
{
    uint8_t reason;                     // 重启原因
}reboot_state_t;

/**
 * @brief 窗帘
 */
typedef struct
{
    uint8_t curtain_state;              // 窗帘状态，curtain_state_t
    uint8_t current_position;           // 当前位置，单位：%，范围：0~100
    uint8_t target_position;            // 目标位置，单位：%，范围：0~100
    uint8_t direction;                  // 方向，0：正转；1：反转
    uint8_t speed_level;                // 速度等级，speed_level_t
}curtain_param_t;


/**
 * @brief 产品设置参数
 */
typedef struct
{
    uint16_t reserve0;                  // 保留
    uint16_t reserve1;                  // 保留
    uint16_t reserve2           : 2;    // 保留
    uint8_t node_mode_enable    : 1;    // 干节点模式显示/隐藏：0不显示，1显示
    uint8_t stroke_enable       : 1;    // 行程设置显示/隐藏：0不显示，1显示
    uint8_t calibration_enable  : 1;    // 电机校准显示/隐藏：0不显示，1显示
    uint8_t direction_enable    : 1;    // 电机反转显示/隐藏：0不显示，1显示
    uint8_t speed_enable        : 1;    // 电机速度显示/隐藏：0不显示，1显示
    uint8_t remote_enable       : 1;    // 遥控器管理显示/隐藏：0不显示，1显示
}gwin_product_cfg_t;


/**
 * @brief 窗帘状态
 */
typedef enum
{
    CURTAIN_STATE_STOP,                 // 关闭
    CURTAIN_STATE_OPEN,                 // 打开
    CURTAIN_STATE_PAUSE,                // 暂停
    CURTAIN_STATE_MAX,
}curtain_state_t;

/**
 * @brief 速度等级
 */
typedef enum
{
    SPEED_LEVEL_LOW,                    // 低速
    SPEED_LEVEL_MID,                    // 中速
    SPEED_LEVEL_HIGH,                   // 高速
    SPEED_LEVEL_MAX,
}speed_level_t;

/**
 * @brief 干节点模式
 */
typedef enum
{
    NODE_MODE_ON_OFF_STOP,              // 开关停
    NODE_MODE_ON_STOP_OFF_STOP,         // 开停/关停
    NODE_MODE_ON_OFF_STOP_LOOP,         // 开关停循环
    NODE_MODE_MAX,
}node_mode_t;

/**
 * @brief 设置
 */
typedef struct
{
    // 一些标志位
    uint32_t upload_total       : 1;    // 参数全部上报

    uint8_t stroke_min;                 // 行程最小值，单位：%，范围：0~50
    uint8_t stroke_max;                 // 行程最大值，单位：%，范围：51~100
    uint8_t node_mode;                  // 干节点模式，node_mode_t

    uint8_t reserve1;                   // 保留
    uint32_t reserve[2];                // 保留
}system_param_setting_t;


/**
 * @brief 系统参数上报表
 */
typedef struct
{
    uint8_t size;
    uint8_t *memory_addr;               // 内存地址
    uint8_t *last_value;                // 某些本地主动修改的参数，跟上次上报值相同就不上报
    uint8_t (*upload_action)(uint32_t value);  // 上报接口
}system_upload_map_t;
/**
 * @brief 系统参数上报编号
 */
typedef enum
{
    SYS_UPLOAD_INDEX_PRODUCT_CFG,       // 设备设置（隐藏某些功能）
//    SYS_UPLOAD_INDEX_CURTAIN_STATE,     // 窗帘状态
    SYS_UPLOAD_INDEX_CURRENT_POSITION,  // 当前位置
    SYS_UPLOAD_INDEX_TARGET_POSITION,   // 目标位置
    SYS_UPLOAD_INDEX_DIRECTION,         // 方向
    SYS_UPLOAD_INDEX_SPEED_LEVEL,       // 速度等级
    SYS_UPLOAD_INDEX_STROKE_MIN,        // 行程最小值
    SYS_UPLOAD_INDEX_STROKE_MAX,        // 行程最大值
    SYS_UPLOAD_INDEX_NODE_MODE,         // 干节点模式
    SYS_UPLOAD_INDEX_MAX,
}system_upload_index_t;
#define SYS_UPLOAD_PER_SECOND_CNT_MAX   3       // 限制每秒钟最多上报条数，减少协议栈压栈压力

/**
 * @brief 上报值 上次
 *          为了减轻服务器压力，少上报参数，某些本地主动修改的参数，跟上次上报值相同就不上报
 */
typedef struct
{
    uint8_t curtain_state;              // 窗帘状态
    uint8_t current_position;           // 当前位置
    uint8_t target_position;            // 目标位置
    uint8_t direction;                  // 方向
    uint8_t speed_level;                // 速度等级

    uint8_t reserve1;                   // 保留
    uint16_t reserve2;                  // 保留
    uint32_t reserve[2];                // 保留
}system_upload_last_t;

/**
 * @brief 上报
 */
typedef struct
{
    uint32_t wait;                      // 待上报记录（暂定最大32个参数），应对状态对不上
    system_upload_last_t last;          // 上报值 上次
}system_upload_t;



/**
 * @brief 系统参数
 */
typedef struct
{
    reboot_state_t reboot_state;        // 重启状态
    network_t network;                  // 配网
    system_upload_t system_upload;      // 上报

    uint8_t system_upload_force_wait;   // 系统参数强制延时，配网、蓝牙直连初期，系统参数强制延时，马上上报可能死机
    uint32_t second;                    // 上电计秒
    curtain_param_t curtain;            // 窗帘参数

    uint32_t system_upload_clock[SYS_UPLOAD_INDEX_MAX]; // 系统参数上报时钟

    // 一些标志位
    union
    {
        struct
        {
            uint8_t reboot_restore_state        : 1;    // 重启还原状态
            uint8_t reset_all_force             : 1;    // 强制复位所有参数（后续可能删除，请看 PRODUCT_MARK_NETWORK_RESET_AUTO）
            uint8_t network_state               : 1;    // 连网状态，0：协议栈未初始化；1：协议栈已初始化，网络协议栈未初始调用协议栈API导致死机（这里不代表已经连上网关！！！！！）
            uint8_t gatt_state                  : 1;    // 蓝牙直连状态
            uint8_t factory_test                : 1;    // 工厂测试
            uint8_t factory_reset               : 1;    // 恢复出厂
            uint8_t network_reset               : 1;    // 重新配网
            uint8_t ota_state                   : 1;    // ota
        };
        uint32_t flag_total;
    };

    gwin_product_cfg_t product_cfg;     // 设备设置（隐藏某些功能）
    system_param_setting_t setting;     // 设置
}system_param_t;


/*-------------------------- Global Variables -------------------------------*/
extern const system_param_setting_t defualt_system_param_setting;

extern const system_upload_map_t system_upload_map[];


/*-------------------------- Local Variables --------------------------------*/

/*-------------------------- Functions Declarations -------------------------*/

/*-------------------------- Functions Definitions --------------------------*/
void gwin_custom_record_check(void);
void gwin_custom_record_load(void);
void gwin_custom_record_save(uint16_t record_id);
void gwin_custom_record_reset(uint16_t record_id);
void gwin_custom_record_reset_all(void);

void gwin_custom_record_reset_all_force_force(void);

void gwin_custom_record_save_reboot_state(uint8_t reason);
void gwin_custom_system_param_init_after_board_init(void);
void gwin_custom_system_param_init_after_ble_init(void);


#endif // __GWIN_GLOBAL_DATA_H__


/*-------------------------- END OF FILE ------------------------------------*/

